/*
 * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
#include "rtfexporter.h"

#include <QFontMetrics>
namespace QSynedit {

RTFExporter::RTFExporter(int tabSize, const QByteArray charset):Exporter(tabSize,charset)
{
    mDefaultFilter = "Rich Text Format Documents (*.rtf)|*.rtf";
    mClipboardFormat = "application/x-qt-windows-mime;value=\"Rich Format Text\"";
    //mClipboardFormat = "Rich Format Text";
    // setup array of chars to be replaced
    mReplaceReserved['\\'] = "\\\\";
    mReplaceReserved['{'] = "\\{";
    mReplaceReserved['}'] = "\\}";
    mReplaceReserved['\t'] = "\\tab";

}

QString RTFExporter::colorToRTF(const QColor &color) const
{
    return QString("\\red%1\\green%2\\blue%3;")
            .arg(color.red())
            .arg(color.green())
            .arg(color.blue());
}

int RTFExporter::getColorIndex(const QColor &color)
{
    int index = mListColors.indexOf(color);
    if (index<0) {
        mListColors.append(color);
        index = mListColors.length()-1;
    }
    return index;
}

QString RTFExporter::getFontTable()
{
    QString result = "{\\fonttbl{\\f0\\fmodern\\fcharset134 "
        + replaceReservedChars(mFont.family());
    result = result + ";}}" + lineBreak();
    return result;
}

void RTFExporter::formatAttributeDone(bool , bool , FontStyles fontStyles)
{
    // nothing to do about the color, but reset the font style
    if (fontStyles.testFlag(FontStyle::fsBold)) {
        mAttributesChanged = true;
        addData("\\b0");
    }
    if (fontStyles.testFlag(FontStyle::fsItalic)) {
        mAttributesChanged = true;
        addData("\\i0");
    }
    if (fontStyles.testFlag(FontStyle::fsUnderline)) {
        mAttributesChanged = true;
        addData("\\ul0");
    }
    if (fontStyles.testFlag(FontStyle::fsStrikeOut)) {
        mAttributesChanged = true;
        addData("\\strike0");
    }
}

void RTFExporter::formatAttributeInit(bool backgroundChanged, bool foregroundChanged, FontStyles fontStyles)
{
    // background color
    if (backgroundChanged) {
        addData(QString("\\chshdng0\\chcbpat%1\\cb%2\\highlight%3 ")
              .arg(getColorIndex(mLastBG))
              .arg(getColorIndex(mLastBG))
              .arg(getColorIndex(mLastBG)));
        mAttributesChanged = true;
    }
    // text color
    if (foregroundChanged) {
        addData(QString("\\cf%1").arg(getColorIndex(mLastFG)));
        mAttributesChanged = true;
    }
    // font styles
    // nothing to do about the color, but reset the font style
    if (fontStyles.testFlag(FontStyle::fsBold)) {
        mAttributesChanged = true;
        addData("\\b0");
    }
    if (fontStyles.testFlag(FontStyle::fsItalic)) {
        mAttributesChanged = true;
        addData("\\i0");
    }
    if (fontStyles.testFlag(FontStyle::fsUnderline)) {
        mAttributesChanged = true;
        addData("\\ul0");
    }
    if (fontStyles.testFlag(FontStyle::fsStrikeOut)) {
        mAttributesChanged = true;
        addData("\\strike0");
    }
    if (mAttributesChanged) {
        addData(" ");
        mAttributesChanged = false;
    }
}

void RTFExporter::formatAfterLastAttribute()
{
    // no need to reset the font style here...
}

void RTFExporter::formatBeforeFirstAttribute(bool backgroundChanged, bool foregroundChanged, FontStyles fontStyles)
{
    formatAttributeInit(backgroundChanged, foregroundChanged, fontStyles);
}

void RTFExporter::formatNewLine()
{
    addNewLine();
    addData("\\par ");
}

QString RTFExporter::getFooter()
{
    return "}";
}

QString RTFExporter::getFormatName()
{
    return "RTF";
}

QString RTFExporter::getHeader()
{
    QFontMetrics fm(mFont);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)    
    int tabWidth = mTabSize * fm.horizontalAdvance("M")*72*20/fm.fontDpi();
#else  
    int tabWidth = mTabSize * fm.horizontalAdvance("M")*72*20/96;
#endif

    QString result = QString("{\\rtf1\\ansi\\deff0\\deftab%1").arg(tabWidth) + getFontTable();
    // all the colors
    result = result + "{\\colortbl";
    for (int i = 0; i<mListColors.count();i++) {
        result = result + colorToRTF(mListColors[i]);
    }
    result = result + colorToRTF(mBackgroundColor);
    result = result + "}" + lineBreak();
    // title and creator comment
    result = result + "{\\info{\\comment Generated by the QSynEdit RTF " +
        "exporter}" + lineBreak();
    result = result + "{\\title " + mTitle + "}}" + lineBreak();
//    if (mUseBackground)
//        Result = Result + { TODO } #13#10;
    result = result + QString("\\deflang1033\\pard\\plain\\f0\\fs%1 ").arg((int)(2 * pixelToPoint(mFont.pixelSize())));
    if (mUseBackground)
        result = result + QString("\\chshdng0\\chcbpat%1\\cb%2\\highlight%3 ")
                .arg(getColorIndex(mLastBG))
                .arg(getColorIndex(mBackgroundColor))
                .arg(getColorIndex(mBackgroundColor));
    return result;
}
}
